﻿using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class ImporterAssetBundle
{
    static Dictionary<string, List<string>> ms_itemGroup = new Dictionary<string, List<string>>();
    static Dictionary<string, string> ms_uiBundles = new Dictionary<string, string>();

    static string[] BundleGroups = {
        Config.UI_ASSETS_PATH + "/panel/items/",
    };

    private static string[] BundleDepends =
    {
        Config.UI_ASSETS_PATH + "/panel/singleitem",
        Config.UI_ASSETS_PATH + "/panel/common_element",
        Config.UI_ASSETS_PATH + "/panel_lr/singleitem",
        Config.UI_ASSETS_PATH + "/panel_lr/common_element",
    };

    static bool IsUINoBuildBundle(string path)
    {
        if (BundleDepends.Any(str => path.Replace("\\", "/").Contains(str)))
            return true;
        return BundleGroups.Any(str => path.Replace("\\", "/").Contains(str));
    }

    public static void Reimport(bool buildLua = false, bool reset = true)
    {
        if (reset) Reset();
        ms_itemGroup.Clear();
        ms_uiBundles.Clear();
        // 着色器
        ReimportShader();
        // 图集
        ReimportAtlas();
        // UI
        ReimportUI();
        ReimportGroups();
        // 动画
        ReimportAnimation();
        // 音乐
        ReimportSound();
        // 场景
        ReimportScene();
        // 特效
        ReimportEffect();
        // 保存AB列表
        SaveBundleList();
        // Lua脚本
        if (buildLua) ReimportLua();

        AssetDatabase.RemoveUnusedAssetBundleNames();
        AssetDatabase.Refresh();
        Debug.Log("AssetBundle Reimport Completed");
    }

    static void ReimportGroup(string path, string suffix, Dictionary<string, string> bundles)
    {
        string strReplacePath = Config.DATA_ASSETS_PATH + "/";
        string abName = path.Replace(strReplacePath, "");

        List<string> files = FileHelper.GetAllChildFiles(path, suffix);
        foreach (string file in files)
        {
            string fileName = file.Replace(strReplacePath, "").Replace(string.Format(".{0}", suffix), "");

            if (!bundles.ContainsKey(fileName))
            {
                bundles.Add(fileName, abName);
            }

            AddUI(fileName, abName);
        }

        ReimportPath(path, abName);
    }

    static void ReimportGroups()
    {
        Dictionary<string, string> bundles = new Dictionary<string, string>();
        foreach (string name in BundleGroups)
        {
            string path = name;
            if (path.EndsWith("/"))
            {
                path = name.Substring(0, path.Length - 1);
            }
            if (Directory.Exists(path))
            {
                ReimportGroup(path, "prefab", bundles);
            }
            if (path.Contains("panel_lr"))
            {
                var panelPath = path.Replace("panel_lr", "panel");
                if (Directory.Exists(panelPath))
                {
                    ReimportGroup(panelPath, "prefab", bundles);
                }
            }
        }

        {
            var iter = ms_itemGroup.GetEnumerator();
            string strReplacePath = Config.DATA_ASSETS_PATH + "/";
            while (iter.MoveNext())
            {
                string abName = iter.Current.Key;
                foreach (string file in iter.Current.Value)
                {
                    bundles.Add(file.Replace(strReplacePath, ""), abName);
                    ReimportPath(file + ".prefab", abName);
                }
            }
        }
        using (var iter = bundles.GetEnumerator())
        {
            while (iter.MoveNext())
            {
                if (IsUI(iter.Current.Key))
                {
                    continue;
                }
                ms_uiBundles.Add(iter.Current.Key.Replace("\\", "/"), iter.Current.Value.Replace("\\", "/"));
            }
        }
        bundles.Clear();
    }

    static bool IsUI(string filename)
    {
        return filename.Contains(Config.UI_PATH + "/panel");
    }

    #region 公用函数
    static void AddUI(string filename, string abname)
    {
        if (filename.Contains(Config.UI_PATH + "/panel"))
        {
            filename = filename.Replace(Config.DATA_ASSETS_PATH + "/", "").Replace(".prefab", "");
            if (!ms_uiBundles.ContainsKey(filename))
            {
                ms_uiBundles.Add(filename, abname);
            }
        }
    }

    static void SaveBundleList()
    {
        // 保存到文件
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine("-- Create by Tool, don`t modify");
            builder.AppendLine();

            builder.AppendLine("BundleDefine = {");
            var iter = ms_uiBundles.GetEnumerator();
            while (iter.MoveNext())
            {
                string prefabName = iter.Current.Key.Replace("\\", "/").ToLower();
                string abName = iter.Current.Value.Replace("\\", "/").ToLower();
                builder.AppendFormat("\t[\"{0}\"] = \"{1}\",\n", prefabName, abName);
            }

            builder.AppendLine("}");
            builder.AppendLine();
            builder.AppendLine("--EOF");

            FileHelper.SaveTextToFile(builder.ToString(), "Assets/Lua/game/define/BundleDefine.lua");
        }
        ms_uiBundles.Clear();
    }

    // 清除Lua资源
    public static void Clear()
    {
        string pathTemp = string.Format("{0}/{1}", Application.dataPath, EditorConfig.TEMP_LUA_PATH);

        FileHelper.DeleteDirectory(pathTemp);
        FileHelper.DeleteFile(pathTemp.Substring(0, pathTemp.LastIndexOf('/')) + ".meta");

        AssetDatabase.Refresh();
    }

    // 清除所有资产的assetbundle信息
    public static void Reset()
    {
        var names = AssetDatabase.GetAllAssetBundleNames();
        foreach (string name in names)
        {
            AssetDatabase.RemoveAssetBundleName(name, true);
        }
    }

    public static void ReimportPath(string path, string name, bool reset = false)
    {
        AssetImporter importer = AssetImporter.GetAtPath(path);
        if (importer == null)
        {
            Debug.LogError(string.Format("Not found Asset Importer path={0} name={1}", path, name));
            return;
        }
        string suffix;
        if (reset)
        {
            name = "";
            suffix = "";
        }
        else
        {
            name = name.ToLower().Replace(" ", "_").Replace("\t", "_").Replace("\\", "_").Replace("/", "_");
            suffix = Config.AB_SUFFIX;
        }
        if (!string.Equals(importer.assetBundleName, name) || !string.Equals(importer.assetBundleVariant, suffix))
            importer.SetAssetBundleNameAndVariant(name, suffix);
    }

    static void ReimportPath(string inPath, string outPath, string suffix, bool reset = false)
    {
        if (!Directory.Exists(inPath))
        {
            Debug.LogError(string.Format("reimport error>>>{0}>=>{1}", inPath, outPath));
            return;
        }
        Debug.Log(string.Format("reimport>>>{0}>=>{1}", inPath, outPath));
        List<string> files = FileHelper.GetAllChildFiles(inPath, suffix);
        for (int i = 0; i < files.Count; ++i)
        {
            string fullpath = files[i];
            if (IsUINoBuildBundle(fullpath))
            {
                continue;
            }
            string name = fullpath.Replace("\\", "/").Replace(inPath, "").Replace(string.Format(".{0}", suffix), "");
            name = string.Format("{0}{1}", outPath, name.ToLower());

            AddUI(fullpath, name);
            ReimportPath(fullpath, name, reset);
        }
    }

    public static void ReimportPathFile(string path, string name, string suffix, bool reset = false)
    {
        if (!Directory.Exists(path))
        {
            return;
        }
        List<string> files = new List<string>();
        FileHelper.GetAllChildFiles(path, suffix, files);
        for (int i = 0; i < files.Count; ++i)
        {
            string fullpath = files[i];
            ReimportPath(fullpath, name, reset);
        }
    }

    static void ReimportDirectory(string path, bool reset = false)
    {
        if (!Directory.Exists(path))
        {
            return;
        }

        string[] dirs = Directory.GetDirectories(path);
        string strReplacePath = Config.DATA_ASSETS_PATH + "/";
        for (int i = 0; i < dirs.Length; ++i)
        {
            string dir = dirs[i];
            string name = dir.Replace(strReplacePath, "").Replace("Assets/", "");

            ReimportPath(dir, name, reset);
        }
    }
    #endregion

    #region 资源导入
    static void ReimportShader()
    {
    }

    static void ReimportAtlas()
    {
        string path = Config.UI_ASSETS_PATH + "/atlas/";
        if (!Directory.Exists(path))
        {
            return;
        }

        ReimportPath(Config.UI_ASSETS_PATH + "/atlas_padding.asset", Config.UI_PATH + "/atlas_padding");

        DirectoryInfo info = new DirectoryInfo(path);
        string strReplacePath = Config.DATA_ASSETS_PATH + "/";
        foreach (FileInfo fi in info.GetFiles())
        {
            if (!fi.Name.EndsWith(".prefab"))
            {
                continue;
            }

            string filename = fi.Name.Substring(0, fi.Name.LastIndexOf("."));
            string abName = string.Format("{0}{1}", path.Replace(strReplacePath, ""), filename);

            ReimportPath(string.Format("{0}{1}.prefab", path, filename), abName);
            ReimportPath(string.Format("{0}{1}_mat.mat", path, filename), abName);
            if (AssetImporter.GetAtPath(string.Format("{0}{1}_mat_dissolve.mat", path, filename)) != null)
            {
                ReimportPath(string.Format("{0}{1}_mat_dissolve.mat", path, filename), abName);
            }
            ReimportPath(string.Format("{0}{1}_c.png", path, filename), abName);
            ReimportPath(string.Format("{0}{1}_a.png", path, filename), abName);
        }
    }

    static void ReimportUI()
    {
        ReimportPath(Config.UI_ASSETS_PATH + "/panel/", Config.UI_PATH + "/panel/", "prefab");
        ReimportPath(Config.UI_ASSETS_PATH + "/panel/", Config.UI_PATH + "/panel/", "prefab");
    }

    static void ReimportAnimation()
    {
    }

    static void ReimportSound()
    {
        ReimportPath(Config.DATA_ASSETS_PATH + "/sound/", "sound/", "prefab");
    }

    static void ReimportScene()
    {

    }

    static void ReimportEffect()
    {

    }

    public static void ReimportLua(bool patch = false)
    {
        if (!patch)
            LuaBuilder.Build();
        ReimportLuaArch(LuaArchType.BIT_32, patch);
    }

    static void ReimportLuaArch(LuaArchType arch, bool patch)
    {
        string path = FileHelper.ConvertArchName(arch, patch ? EditorConfig.TEMP_LUA_PATCH_PATH : EditorConfig.TEMP_LUA_PATH);
        string name = FileHelper.ConvertArchName(arch, patch ? Config.LUA_PATCH : Config.LUA_PACKAGE);
        if (Config.LUA_DATA)
        {
            path = string.Format("Assets/{0}/{1}.asset", path, Config.LUA_PACKAGE);
            ReimportPath(path, name);
        }
        else
        {
            path = string.Format("Assets/{0}/{1}", path, Config.LUA_PACKAGE);

            DirectoryInfo info = new DirectoryInfo(path);
            foreach (FileInfo fi in info.GetFiles())
            {
                if (!fi.Name.EndsWith(".bytes"))
                {
                    continue;
                }
                ReimportPath(string.Format("{0}/{1}", path, fi.Name), name);
            }
        }
    }
    #endregion
}